home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / DIZZY / SRC / SIMSIM.C < prev    next >
Text File  |  1990-12-29  |  7KB  |  294 lines

  1. /*
  2. >>    Dizzy 1.0    SimSim.c
  3. >>
  4. >>    A digital circuit simulator & design program for the X Window System
  5. >>
  6. >>    Copyright 1990 Juri Munkki, all rights reserved
  7. >>
  8. >>    Please read the included file called "DizzyDoc" for information on
  9. >>    what your rights are concerning this product.
  10. >>
  11. >>    The output values are stored in a shifting variable. The current value
  12. >>    is stored as the second-least significant bit and new (possibly unknown)
  13. >>    value is stored as 1. This way you can detect the last n (where n is the
  14. >>    number of bits in int-1) changes in the signal.
  15. >>
  16. >>    This is a very simple (and inefficient) simulation system, but it does
  17. >>    the work quite well. I recommend an event based system, if you want to
  18. >>    improve the simulation drastically. An event based system will require
  19. >>    changes in the "Element" data type and other structures.
  20. */
  21.  
  22. #include "dizzy.h"
  23.  
  24. extern    char    HexDigits[];    /*    "01234567890ABCDEF"    */
  25.  
  26. /*
  27. >>    Read the output indicated by an input.
  28. */
  29. int     ReadOutput(Inp)
  30. Input    *Inp;
  31. {
  32.     if(Inp->Chip)
  33.     {    return(((Element *)(SimBase+Inp->Chip))->Out[Inp->Pin].Data);
  34.     }
  35.     return 0;
  36. }
  37. /*
  38. >>    Simulate a custom chip.
  39. */
  40. void    ResolveCustom(elem)
  41. Element *elem;
  42. {
  43.     int             i;
  44.     Input            *ip;
  45.     TableHeader     *customheader,*oldheader;
  46.     Ptr             newbaseptr,oldbaseptr;
  47.     long            offs;
  48.     Element         *subelem;
  49.  
  50.     elem->Flags |= RESOLVED;
  51.     ip=(Input *)&elem->Out[elem->Outputs];
  52.     customheader=(TableHeader *)(ip+elem->Inputs);
  53.     oldheader=CurHeader;
  54.     newbaseptr=(Ptr)customheader;
  55.     oldbaseptr=SimBase;
  56.  
  57.     for(offs=customheader->First;offs<customheader->Last;offs+=subelem->Length)
  58.     {    subelem=(Element *)(newbaseptr+offs);
  59.         if(subelem->Type==INPT)
  60.         {    subelem->Out[0].Data=ConnectorValue(ip++)>>1;
  61.         }
  62.     }
  63.     SimLevel++;
  64.     SimBase=newbaseptr;
  65.     CurHeader=customheader;
  66.  
  67.     RunSimulation();
  68.  
  69.     i=0;
  70.     for(offs=customheader->First;offs<customheader->Last;offs+=subelem->Length)
  71.     {    subelem=(Element *)(newbaseptr+offs);
  72.         if(subelem->Type==OUTP)
  73.         {    elem->Out[i++].Data=ConnectorValue((Input *)(subelem->Out+1));
  74.         }
  75.     }
  76.  
  77.     CurHeader=oldheader;
  78.     SimBase=oldbaseptr;
  79.     SimLevel--;
  80. }
  81.  
  82. /*
  83. >>    Find out the value of a zero-delay device such as a connector,
  84. >>    an output or a custom chip. Uses recursion.
  85. */
  86. int     ConnectorValue(Inp)
  87. Input    *Inp;
  88. {
  89.     Element *elem;
  90.     
  91.     if(Inp->Chip)
  92.     {    elem=(Element *)(SimBase+Inp->Chip);
  93.         
  94.         if(elem->Flags & RESOLVED)
  95.         {    return    elem->Out[Inp->Pin].Data;
  96.         }
  97.         else
  98.         {    elem->Flags |= RESOLVED;
  99.             if(elem->Type==CONN || elem->Type==OUTP)
  100.             {    elem->Out[Inp->Pin].Data=ConnectorValue((Input *)&elem->Out[1]);
  101.                 return    elem->Out[Inp->Pin].Data;
  102.             }
  103.             else
  104.             if(elem->Type==CUST)
  105.             {    ResolveCustom(elem);
  106.                 return    elem->Out[Inp->Pin].Data;
  107.             }
  108.             else
  109.             {    return    elem->Out[Inp->Pin].Data;
  110.             }
  111.         }
  112.     }
  113.     else
  114.     {    return 0;
  115.     }
  116. }
  117. /*
  118. >>    Run a single "step" of the simulation. Go through all elements
  119. >>    and recalculate new values.
  120. */
  121. void    RunSimulation()
  122. {
  123.     register    Element     *elem;
  124.     register    long        offs;
  125.     register    int         i,a;
  126.                 Input        *ip;
  127.                 Rect        Eraser;
  128.  
  129.     /*    Mark all chips as unresolved.    */
  130.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  131.     {    elem=(Element *)(SimBase+offs);
  132.         elem->Flags &= ~ RESOLVED;
  133.         for(i=0;i<elem->Outputs;i++)
  134.         {    elem->Out[i].Data <<= 1;
  135.         }
  136.     }
  137.     /*    Resolve CONNectors, OUTPuts and CUSTom chips first.    */
  138.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  139.     {    elem=(Element *)(SimBase+offs);
  140.         if(elem->Type==CONN || elem->Type==OUTP)
  141.         {    elem->Flags |= RESOLVED;
  142.             elem->Out[0].Data = ConnectorValue((Input *)&elem->Out[1]);
  143.         }
  144.         else
  145.         if(elem->Type==CUST)
  146.         {    if(!(elem->Flags & RESOLVED))
  147.                 ResolveCustom(elem);
  148.         }
  149.     }
  150.     /*    Resolve all other elements now. These elements have a
  151.     >>    delay of at least one step.
  152.     */
  153.     for(offs=CurHeader->First;offs<CurHeader->Last;offs+=elem->Length)
  154.     {    elem=(Element *)(SimBase+offs);
  155.         ip=(Input *)&elem->Out[elem->Outputs];
  156.  
  157.         switch(elem->Type)
  158.         {    case AND_:
  159.             case NAND:
  160.                 a=NEWVALUE;
  161.                 for(i=0;i<elem->Inputs;i++)
  162.                 {    if(!(ReadOutput(ip++) & CURRENTVALUE))
  163.                     {    a=0;
  164.                         i=elem->Inputs;
  165.                     }
  166.                 }
  167.                 elem->Out[0].Data |= a;
  168.                 if(elem->Type == NAND)
  169.                 {    elem->Out[0].Data ^= NEWVALUE;
  170.                 }
  171.                 break;
  172.             case OR__:
  173.             case NOR_:
  174.                 a=0;
  175.                 for(i=0;i<elem->Inputs;i++)
  176.                 {    if((ReadOutput(ip++) & CURRENTVALUE))
  177.                     {    a=NEWVALUE;
  178.                         i=elem->Inputs;
  179.                     }
  180.                 }
  181.                 elem->Out[0].Data |= a;
  182.                 if(elem->Type == NOR_)
  183.                 {    elem->Out[0].Data ^= NEWVALUE;
  184.                 }
  185.                 break;
  186.             case XOR_:
  187.             case NXOR:
  188.                 a=0;
  189.                 for(i=0;i<elem->Inputs;i++)
  190.                 {    if((ReadOutput(ip++) & CURRENTVALUE))
  191.                     {    a^=NEWVALUE;
  192.                     }
  193.                 }
  194.                 elem->Out[0].Data |= a;
  195.                 if(elem->Type == NXOR)
  196.                 {    elem->Out[0].Data ^= NEWVALUE;
  197.                 }
  198.                 break;
  199.             case RS__:
  200.                 i=ReadOutput(ip++) & CURRENTVALUE;
  201.                 a=ReadOutput(ip++) & CURRENTVALUE;
  202.                 if(i || (elem->Out[1].Data & CURRENTVALUE)) elem->Out[1].Data |= NEWVALUE;
  203.                 if(a || (elem->Out[0].Data & CURRENTVALUE)) elem->Out[0].Data |= NEWVALUE;
  204.  
  205.                 if(i)    elem->Out[0].Data &= ~NEWVALUE;
  206.                 if(a)    elem->Out[1].Data &= ~NEWVALUE;
  207.                 break;
  208.  
  209.             case D___:
  210.                 i=(ReadOutput(ip++) & CURRENTVALUE)>>1;
  211.                 a=ReadOutput(ip++);
  212.  
  213.                 if((a & CURRENTVALUE) && !(a & OLDVALUE))
  214.                 {    elem->Out[0].Data |= i;
  215.                 }
  216.                 else
  217.                 {    elem->Out[0].Data |= (elem->Out[0].Data & CURRENTVALUE)>>1;
  218.                 }
  219.                 elem->Out[1].Data= ~elem->Out[0].Data;
  220.                 break;
  221.             case JK__:
  222.             
  223.                 a=ReadOutput(ip+1);
  224.                 
  225.                 if((a & CURRENTVALUE) && !(a & OLDVALUE))
  226.                 {
  227.                     if(ReadOutput(ip) & CURRENTVALUE)    i=1;
  228.                     else                                i=0;
  229.                     if(ReadOutput(ip+2) & CURRENTVALUE) i|=2;
  230.                     switch(i)
  231.                     {    case 0:
  232.                             elem->Out[0].Data |= (elem->Out[0].Data & CURRENTVALUE)>>1;
  233.                             break;
  234.                         case 1:
  235.                             elem->Out[0].Data |= NEWVALUE;
  236.                             break;
  237.                         case 3:
  238.                             elem->Out[0].Data |= (elem->Out[1].Data & CURRENTVALUE)>>1;
  239.                             break;
  240.                     }
  241.                 }
  242.                 else
  243.                 {    elem->Out[0].Data |= (elem->Out[0].Data & CURRENTVALUE)>>1;
  244.                 }
  245.                 elem->Out[1].Data= ~elem->Out[0].Data;
  246.                 break;
  247.             case NOT_:
  248.                 if(!(ReadOutput(ip) & CURRENTVALUE))
  249.                     elem->Out[0].Data |= NEWVALUE;
  250.                 break;
  251.             case CLOK:
  252.                 if(SimTimer & (1<<elem->PrivData))
  253.                     elem->Out[0].Data |= NEWVALUE;
  254.                 break;
  255.             case ZERO:
  256.                 break;
  257.             case ONE_:
  258.                 elem->Out[0].Data |= NEWVALUE;
  259.                 break;
  260.             case OUTP:
  261.                 if(SimLevel==0)
  262.                 if(((elem->Out[0].Data & CURRENTVALUE) ? 0 : 1) ^
  263.                    ((elem->Flags & DISPLAYEDVALUE) ? 0 : 1))
  264.                 {    Eraser=elem->Body;
  265.                     InsetRect(&Eraser,1,1);
  266.                     EraseRect(&Eraser);
  267.                     MoveTo(elem->Body.left+6,elem->Body.bottom-4);
  268.                     elem->Flags ^= DISPLAYEDVALUE;
  269.                     DrawChar(elem->Flags & DISPLAYEDVALUE ? '1' : '0');
  270.                 }
  271.                 break;
  272.             case HEXD:
  273.                 if(SimLevel)    break;
  274.                 a=0;
  275.                 for(i=0;i<4;i++)
  276.                 {    a = (a>>1) | ((ReadOutput(ip++) & CURRENTVALUE) ? 8 : 0);
  277.                 }
  278.                 if(a!=elem->PrivData)
  279.                 {    Eraser=elem->Body;
  280.                     InsetRect(&Eraser,1,1);
  281.                     EraseRect(&Eraser);
  282.                     MoveTo(elem->Body.left+6,elem->Body.bottom-28);
  283.                     elem->PrivData=a;
  284.                     DrawChar(HexDigits[elem->PrivData]);
  285.                 }
  286.                 break;
  287.             case INPT:
  288.                 if(elem->Out[0].Data & CURRENTVALUE)
  289.                     elem->Out[0].Data |= NEWVALUE;
  290.                 break;
  291.         }
  292.     }
  293. }
  294.